package com.lyy.weather.bean;

import android.content.Context;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;

import com.lyy.weather.R;

public class RefreshableView extends LinearLayout implements View.OnTouchListener {
    //下拉状态
    public static final int PULL_TO_REFRESH=0;
    //释放立即刷新
    public static final int RELEASE_TO_REFRESH=1;
    //正在刷新
    public static final int REFREASHING=2;
    //刷新完成or未刷新状态
    public static final int FINISHED_REFRESH=3;

    //下拉条回滚速度
    public static final int SCROLL_SPEED=-20;

    //下拉刷新的回调接口
    private PullToRefreshListener mListener;

    //下拉头的view
    private View header;

    //需要去下拉的ListView
    private ListView listView;

    //刷新时显示的进度条
    private ProgressBar progressBar;

    //下拉头的布局参数
    private MarginLayoutParams headerLayoutParams;

    //下拉头的高度
    private int hideHeaderHeight;

    //当前处理的状态
    //可选   PULL_TO_REFRESH
    //    RELEASE_TO_REFRESH
    //    REFREASHING
    //   FINISHED_REFRESH
    private int currentStatus=FINISHED_REFRESH;

    //记录上一次的状态，避免重复操作
    private int lastStatus=currentStatus;

    //手指按下时的屏幕纵坐标
    private float yDown;

    //滚动之前用户手指可以移动的最大值
    private int touchSlop;

    //是否已加载过一次Layout，onLayout中的初始化只需加载一次
    private boolean loadOnce;

    //当前是否下来，ListView到头才允许下拉
    private boolean ableToPull;

    /**
     * 下拉刷新控件的构造函数，会在运行时动态添加一个下拉头的布局。
     *
     * @param context
     * @param attrs
     */
    public RefreshableView(Context context, AttributeSet attrs){
        super(context,attrs);
        header= LayoutInflater.from(context).inflate(R.layout.header_refresh,null,true);
        progressBar=(ProgressBar)header.findViewById(R.id.progress_header);
        touchSlop= ViewConfiguration.get(context).getScaledTouchSlop();
      //  refreshUpdatedAtValue();
        setOrientation(VERTICAL);
        addView(header,0);
    }

    /**
     * 进行一些关键性的初始化操作，比如：将下拉头向上偏移进行隐藏，给ListView注册touch事件。
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (changed && !loadOnce) {
            //隐藏下拉头
            hideHeaderHeight = -header.getHeight();
            headerLayoutParams = (MarginLayoutParams) header.getLayoutParams();
            headerLayoutParams.topMargin = hideHeaderHeight;
            //注册点击事件
            listView = (ListView) getChildAt(1);
            listView.setOnTouchListener(this);
            //加载过一次了
            loadOnce = true;
        }
    }

    /**
     * 当ListView被触摸时调用，其中处理了各种下拉刷新的具体逻辑。
     */
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //判断是否可以下拉刷新
        setIsAbleToPull(event);
        if(ableToPull){
            switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    yDown=event.getRawY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    float yMove=event.getRawY();
                    int distance=(int)(yMove-yDown);
                    //如果手指是下滑状态，但下拉头完全隐藏，就屏蔽下拉事件
                    if(distance<=0&&headerLayoutParams.topMargin<=hideHeaderHeight){
                        return false;
                    }
                    if(distance<touchSlop){
                        return false;
                    }
                    if(currentStatus!=REFREASHING){
                        if(headerLayoutParams.topMargin>0){
                            currentStatus=RELEASE_TO_REFRESH;
                        }else {
                            currentStatus=PULL_TO_REFRESH;
                        }
                        // 通过偏移下拉头的topMargin值，来实现下拉效果
                        headerLayoutParams.topMargin = (distance / 2) + hideHeaderHeight;
                        header.setLayoutParams(headerLayoutParams);
                    }
                    break;
                    case MotionEvent.ACTION_UP:
                default:
                    if(currentStatus==RELEASE_TO_REFRESH){
                        //松手是立即刷新状态，就去调用正在刷新的任务
                        new RefreshingTask().execute();
                    }else if(currentStatus==PULL_TO_REFRESH){
                        //松手时是下拉状态，隐藏下拉头
                        new HideHeaderTask().execute();
                    }
                    break;
            }
            //时刻记得更新下拉头中的信息
            if(currentStatus==PULL_TO_REFRESH||currentStatus==RELEASE_TO_REFRESH){
                updateHeaderView();
                // 当前正处于下拉或释放状态，要让ListView失去焦点，否则被点击的那一项会一直处于选中状态
                listView.setPressed(false);
                listView.setFocusable(false);
                listView.setFocusableInTouchMode(false);
                lastStatus = currentStatus;
                // 当前正处于下拉或释放状态，通过返回true屏蔽掉ListView的滚动事件
                return true;

            }
        }
        return false;
    }

    /**
     * 给下拉刷新控件注册一个监听器
     *
     * @param  listener
     *      监听器的实现
     */

    public void setOnRefreshListener(PullToRefreshListener listener){
        mListener=listener;
    }

    /**
     * 当所有的刷新逻辑完成后，记录调用一下，否则listView将一直处于正在刷新状态
     */
    public void finishRefreshing(){
        currentStatus=FINISHED_REFRESH;
        //隐藏下拉头
        new HideHeaderTask().execute();
    }

/**
 * 根据当前ListView的滚动状态来设定 {@link #ableToPull}
 * 的值，每次都需要在onTouch中第一个执行，这样可以判断出当前应该是滚动ListView，还是应该进行下拉。
 *
 * @param event
*/
   private void setIsAbleToPull(MotionEvent event){
       View firstChild=listView.getChildAt(0);
       if(firstChild!=null){
           int firstVisiblePos=listView.getFirstVisiblePosition();
           if(firstVisiblePos==0&&firstChild.getTop()==0){
               if(!ableToPull){
                   yDown=event.getRawY();
               }
               // 如果首个元素的上边缘，距离父布局值为0，就说明ListView滚动到了最顶部，此时应该允许下拉刷新
               ableToPull = true;
           }else{
               if(headerLayoutParams.topMargin!=hideHeaderHeight){
                   headerLayoutParams.topMargin=hideHeaderHeight;
                   header.setLayoutParams(headerLayoutParams);
               }
               ableToPull=false;
           }
       }else{
           //如果没有元素，也应该允许下拉刷新
           ableToPull=true;
       }
   }

    /**
     * 更新下拉头中的信息
     */
    private void updateHeaderView(){
        if(lastStatus!=currentStatus){
            if(currentStatus==PULL_TO_REFRESH){
                progressBar.setVisibility(View.VISIBLE);
            }else if(currentStatus==RELEASE_TO_REFRESH){
                progressBar.setVisibility(View.GONE);
            }else if(currentStatus==REFREASHING){
                progressBar.setVisibility(View.VISIBLE);
            }
        }
        //refreshUpdateAtValue();
    }


    /**
     * 正在刷新的任务，在此任务中会回调注册进来的下拉刷新监听器
     */
    class RefreshingTask extends AsyncTask<Void,Integer,Void>{
        @Override
        protected Void doInBackground(Void... voids) {
            int topMargin=headerLayoutParams.topMargin;
            while(true){
                topMargin=topMargin+SCROLL_SPEED;
                if(topMargin<=0){
                    topMargin=0;
                    break;
                }
                publishProgress(topMargin);
                sleep(10);
            }
            currentStatus=REFREASHING;
            publishProgress(0);
            if(mListener!=null){
                mListener.onRefresh();
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... topMargin) {
            updateHeaderView();
            headerLayoutParams.topMargin=topMargin[0];
            header.setLayoutParams(headerLayoutParams);
        }
    }

    /**
     * 隐藏下拉头的任务
     */
    class HideHeaderTask extends AsyncTask<Void,Integer,Integer>{

        @Override
        protected Integer doInBackground(Void... voids) {
            int topMargin=headerLayoutParams.topMargin;
            while(true){
                topMargin=topMargin+SCROLL_SPEED;
                if(topMargin<=hideHeaderHeight){
                    topMargin=hideHeaderHeight;
                    break;
                }
                publishProgress(topMargin);
                sleep(10);
            }
            return topMargin;
        }

        @Override
        protected void onProgressUpdate(Integer... topMargin) {
            headerLayoutParams.topMargin=topMargin[0];
            header.setLayoutParams(headerLayoutParams);
        }

        @Override
        protected void onPostExecute(Integer topMagin) {
            headerLayoutParams.topMargin=topMagin;
            header.setLayoutParams(headerLayoutParams);
            currentStatus=FINISHED_REFRESH;
        }
    }

    /**
     * 使当前线程睡眠指定的毫秒数。
     *
     * @param time
     *            指定当前线程睡眠多久，以毫秒为单位
     */
    private void sleep(int time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    /**
     * 下拉刷新的监听器，使用下拉刷新的地方应该注册此监听器来获取刷新回调。
     *
     */
    public interface PullToRefreshListener {

        /**
         * 刷新时会去回调此方法，在方法内编写具体的刷新逻辑。注意此方法是在子线程中调用的， 你可以不必另开线程来进行耗时操作。
         */
        void onRefresh();

    }




}
